/*
 * This file Copyright (c) 2015. Walle.
 * (http://www.wallellen.com). All rights reserved.
 *
 *
 * This file is dual-licensed under both the
 * Walle Agreement (WA) and the GNU General Public License.
 * You may elect to use one or the other of these licenses.
 *
 * This file is distributed in the hope that it will be
 * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
 * Redistribution, except as permitted by whichever of the GPL
 * or WA you select, is prohibited.
 *
 * 1. For the GPL license (GPL), you can redistribute and/or
 * modify this file under the terms of the GNU General
 * Public License, Version 3, as published by the Free Software
 * Foundation.  You should have received a copy of the GNU
 * General Public License, Version 3 along with this program;
 * if not, write to the Free Software Foundation, Inc., 51
 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * 2. For the Walle Agreement (WA), this file
 * and the accompanying materials are made available under the
 * terms of the WA which accompanies this distribution, and
 * is available at http://www.wallellen.com/agreement.html
 *
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 */

package com.wallellen.authority.service.impl;

import com.wallellen.authority.dao.OrganizationDaoInter;
import com.wallellen.authority.dao.PostActionDaoInterface;
import com.wallellen.authority.dao.PostDaoInter;
import com.wallellen.authority.dao.UserDaoInterface;
import com.wallellen.authority.dao.UserPostDaoInterface;
import com.wallellen.authority.domain.Organization;
import com.wallellen.authority.domain.Post;
import com.wallellen.authority.domain.Postaction;
import com.wallellen.authority.service.OrganizationServiceInterface;
import com.wallellen.core.auth.domain.LoginUser;
import com.wallellen.core.sql.query.DBRule;
import com.wallellen.core.sql.query.DBSort;
import com.wallellen.core.sql.query.DataQuery;
import com.wallellen.core.sql.result.DataResult;
import com.wallellen.core.time.TimeTool;
import com.wallellen.web.easy.EasyUiTreeNode;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * Created by walle on 12/12/15.
 */
@Service
public class OrganizationServiceImpl
        implements OrganizationServiceInterface {

    @Resource
    private OrganizationDaoInter organizationDao;

    @Resource
    private PostDaoInter postDao;

    @Resource
    private UserPostDaoInterface userpostDao;

    @Resource
    private PostActionDaoInterface postactionDao;

    @Resource
    private UserDaoInterface userDao;

    @Transactional
    public Organization insertOrganizationEntity(Organization entity, LoginUser user) {
        entity.setCuser(user.getId());
        entity.setCtime(TimeTool.getTimeDate14());
        entity.setMuser(user.getId());
        entity.setUtime(TimeTool.getTimeDate14());
        entity.setState("1");
        if (entity.getParentid() == null) {
            entity.setParentid("NONE");
        }
        entity.setTreecode("NONE");
        entity = this.organizationDao.insertEntity(entity);
        initTreeCode(entity.getId());
        return entity;
    }

    @Transactional
    public Organization editOrganizationEntity(Organization entity, LoginUser user) {
        Organization entity2 = this.organizationDao.getEntity(entity.getId());
        entity2.setMuser(user.getId());
        entity2.setUtime(TimeTool.getTimeDate14());
        entity2.setType(entity.getType());
        entity2.setSort(entity.getSort());
        entity2.setState(entity.getState());
        entity2.setComments(entity.getComments());
        entity2.setName(entity.getName());
        this.organizationDao.editEntity(entity2);
        return entity2;
    }

    @Transactional
    public void deleteOrganizationEntity(String id, LoginUser user) {
        if (this.organizationDao.selectEntitys(DBRule.addRule(new ArrayList(), "parentid", id, "=")).size() > 0) {
            throw new RuntimeException("不能删除该节点，请先删除其子节点");
        }

        for (Post post : this.postDao.selectEntitys(new DBRule("ORGANIZATIONID", id, "=").getDBRules())) {
            deletePostEntity(post.getId(), user);
        }

        this.organizationDao.deleteEntity(this.organizationDao.getEntity(id));
    }

    @Transactional
    public Organization getOrganizationEntity(String id) {
        if (id == null) {
            return null;
        }
        return this.organizationDao.getEntity(id);
    }

    @Transactional
    public DataQuery createOrganizationSimpleQuery(DataQuery query) {
        DataQuery dbQuery = DataQuery.init(query, "ALONE_AUTH_ORGANIZATION",
                "ID,TYPE,SORT,PARENTID,MUSER,CUSER,STATE,UTIME,CTIME,COMMENTS,NAME,TREECODE");
        return dbQuery;
    }

    @Transactional
    public void deletePostEntity(String id, LoginUser user) {
        String[] ids = id.split(",");
        for (String id1 : ids) {
            this.userpostDao.deleteEntitys(new DBRule("POSTID", id1, "=").getDBRules());

            this.postactionDao.deleteEntitys(new DBRule("POSTID", id1, "=").getDBRules());
            this.postDao.deleteEntity(this.postDao.getEntity(id1));
        }
    }

    @Transactional
    public Post getPostEntity(String id) {
        if (id == null) {
            return null;
        }
        return this.postDao.getEntity(id);
    }

    @Transactional
    public DataQuery createPostSimpleQuery(DataQuery query) {
        DataQuery dbQuery = DataQuery.init(query, "ALONE_AUTH_POST",
                "ID,EXTENDIS,NAME,ORGANIZATIONID,PSTATE,EUSER,EUSERNAME,CUSER,CUSERNAME,ETIME,CTIME");
        return dbQuery;
    }

    @Transactional
    public void moveOrgTreeNode(String orgId, String targetOrgId) {
        String[] orgIds = orgId.split(",");
        for (int i = 0; i < orgIds.length; i++) {
            Organization node = getOrganizationEntity(orgIds[i]);

            Organization target = getOrganizationEntity(targetOrgId);
            if (target.getTreecode().indexOf(node.getTreecode()) >= 0) {
                throw new RuntimeException("不能够移动到其子节点下!");
            }
            node.setParentid(targetOrgId);
            this.organizationDao.editEntity(node);

            List<Organization> list = this.organizationDao.getAllSubNodes(orgIds[i]);
            for (Organization org : list)
                initTreeCode(org.getId());
        }
    }

    private void initTreeCode(String treeNodeId) {
        Organization node = getOrganizationEntity(treeNodeId);
        if (node.getParentid().equals("NONE"))
            node.setTreecode(node.getId());
        else {
            node.setTreecode(this.organizationDao.getEntity(node.getParentid()).getTreecode() + node.getId());
        }
        this.organizationDao.editEntity(node);
    }

    @Transactional
    public Post editPost(String postId, String postname, String extendis, LoginUser user) {
        Post post = this.postDao.getEntity(postId);
        post.setName(postname);
        post.setExtendis(extendis);
        post.setEtime(TimeTool.getTimeDate14());
        post.setEuser(user.getId());
        post.setEusername(user.getName());
        this.postDao.editEntity(post);

        this.userpostDao.deleteEntitys(new DBRule("POSTID", post.getId(), "=").getDBRules());
        return post;
    }

    @Transactional
    public Post insertPost(String orgId, String postname, String extendis, LoginUser user) {
        Post post = new Post();
        post.setName(postname);
        post.setExtendis(extendis);
        post.setCtime(TimeTool.getTimeDate14());
        post.setCuser(user.getId());
        post.setCusername(user.getName());
        post.setEtime(TimeTool.getTimeDate14());
        post.setEuser(user.getId());
        post.setEusername(user.getName());
        post.setOrganizationid(orgId);
        post.setPstate("1");
        return this.postDao.insertEntity(post);
    }

    @Transactional
    public List<EasyUiTreeNode> loadPostTree(String ids) {
        if ((ids == null) || (ids.trim().length() <= 0)) {
            ids = "NONE";
        }
        DataQuery query = DataQuery.getInstance("1", "NAME,PARENTID,ID,UTYPE",
                "(SELECT NAME,PARENTID,ID,'11' AS UTYPE,SORT FROM alone_auth_organization  UNION SELECT NAME,ORGANIZATIONID AS PARENTID,ID,TYPE AS UTYPE,1000 as SORT FROM alone_auth_post  ) a ");
        query.setPagesize(1000);
        query.addRule(new DBRule("PARENTID", ids, "="));
        query.setNoCount();
        query.addSort(new DBSort("UTYPE", "asc"));
        query.addSort(new DBSort("SORT", "asc"));
        DataQuery query2 = DataQuery.getInstance("1",
                "a.NAME as NAME,a.PARENTID as PARENTID,a.ID as ID,a.UTYPE as UTYPE",
                "alone_auth_organization b LEFT JOIN (SELECT NAME,PARENTID,ID,'0' AS UTYPE FROM alone_auth_organization  UNION SELECT NAME,ORGANIZATIONID AS PARENTID,ID,TYPE AS UTYPE FROM alone_auth_post  ) a ON a.PARENTID=b.ID");
        query2.setPagesize(1000);
        query2.addRule(new DBRule("b.PARENTID", ids, "="));
        query2.setNoCount();
        List list = null;
        try {
            List<Map<String, Object>> listOne = query.search().getResultList();
            for (Map node : listOne) {
                if (node.get("UTYPE").equals("1")) {
                    node.put("UTYPE", "icon-suppliers");
                }
                if (node.get("UTYPE").equals("2")) {
                    node.put("UTYPE", "icon-user_medical");
                }
            }
            list = EasyUiTreeNode.formatAsyncAjaxTree(listOne, query2.search().getResultList(), "PARENTID", "ID",
                    "NAME", "UTYPE");
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        return list;
    }

    @Transactional
    public void addUserPost(String userId, String postId, LoginUser currentUser) {
    }

    public OrganizationDaoInter getOrganizationDao() {
        return this.organizationDao;
    }

    public void setOrganizationDao(OrganizationDaoInter dao) {
        this.organizationDao = dao;
    }

    public PostDaoInter getPostDao() {
        return this.postDao;
    }

    public void setPostDao(PostDaoInter postDao) {
        this.postDao = postDao;
    }

    public PostActionDaoInterface getPostactionDao() {
        return this.postactionDao;
    }

    public void setPostactionDao(PostActionDaoInterface postactionDao) {
        this.postactionDao = postactionDao;
    }

    public UserPostDaoInterface getUserpostDao() {
        return this.userpostDao;
    }

    public void setUserpostDao(UserPostDaoInterface userpostDao) {
        this.userpostDao = userpostDao;
    }

    public UserDaoInterface getUserDao() {
        return this.userDao;
    }

    public void setUserDao(UserDaoInterface userDao) {
        this.userDao = userDao;
    }

    @Transactional
    public void removePostUsers(String postId, String userid, LoginUser currentUser) {
        String[] userIds = userid.split(",");
        for (String userId : userIds)
            this.userpostDao.deleteEntitys(new DBRule("USERID", userId, "=").addRule("POSTID", postId, "=").getDBRules());
    }

    @Transactional
    public void setPostActionTree(List<String> actionTreeIds, String postId) {
        if ((postId == null) || (postId.trim().length() <= 0)) {
            throw new IllegalArgumentException("请选择一个岗位");
        }

        this.postactionDao.deleteEntitys(new DBRule("POSTID", postId, "=").getDBRules());
        for (String nodeId : actionTreeIds) {
            Postaction postaction = new Postaction();
            postaction.setMenuid(nodeId);
            postaction.setPostid(postId);
            this.postactionDao.insertEntity(postaction);
        }
    }

    @Transactional
    public List<Organization> getTree() {
        return this.organizationDao.selectEntitys(new DBRule("1", "1", "=").getDBRules());
    }

    public List<Map<String, Object>> getPostList(String orgId) {
        try {
            DataQuery query = DataQuery.getInstance(1,
                    "POST.ID AS POSTID, POST.NAME AS POSTNAME, ORG.ID AS ORGID, ORG.NAME AS ORGNAME ",
                    "ALONE_AUTH_POST POST INNER JOIN ALONE_AUTH_ORGANIZATION ORG ON POST.ORGANIZATIONID = ORG.ID");
            query.setNoCount();
            query.addRule(new DBRule("POST.ORGANIZATIONID", orgId, "="));
            DataResult result = query.search();
            return result.getResultList();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return null;
    }

    @Transactional
    public List<Map<String, Object>> getPostListWithPOrgPost(String orgId) {
        if ((orgId == null) || (orgId.isEmpty())) {
            return new ArrayList();
        }

        Organization entity = this.organizationDao.getEntity(orgId);
        String treecode = entity.getTreecode();
        String pOrgIds = "";
        for (int i = 1; i <= (treecode.length() - 32) / 32; i++) {
            pOrgIds = pOrgIds + "'" + treecode.substring((i - 1) * 32, i * 32) + "'";
            if (i <= (treecode.length() - 64) / 32) {
                pOrgIds = pOrgIds + ",";
            }
        }
        if (pOrgIds.isEmpty()) {
            pOrgIds = "''";
        }
        try {
            DataQuery query = DataQuery.getInstance(1,
                    "a.POSTID AS POSTID, a.POSTNAME AS POSTNAME, a.ORGID AS ORGID, a.ORGNAME AS ORGNAME ",
                    "(SELECT PPOST.ID AS POSTID, PPOST.NAME AS POSTNAME, PORG.ID AS ORGID, PORG.NAME AS ORGNAME FROM ALONE_AUTH_ORGANIZATION PORG LEFT JOIN ALONE_AUTH_POST PPOST ON PORG.ID = PPOST.ORGANIZATIONID WHERE PPOST.EXTENDIS = '1' AND PORG.ID IN (" +
                            pOrgIds + ") /* 查找父机构可用的岗位 */" +
                            "UNION ALL " +
                            "SELECT POST.ID AS POSTID, POST.NAME AS POSTNAME, ORG.ID AS ORGID, ORG.NAME AS ORGNAME " +
                            "FROM ALONE_AUTH_ORGANIZATION ORG " +
                            "LEFT JOIN ALONE_AUTH_POST POST ON ORG.ID = POST.ORGANIZATIONID " + "WHERE ORG.ID = '" +
                            orgId + "' /* 查找当前机构所有的岗位 */) a ");
            query.setNoCount();
            DataResult result = query.search();
            return result.getResultList();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return null;
    }

    @Transactional
    public List<Organization> getParentOrgs(String orgid) {
        String id = orgid;
        List orgs = new ArrayList();
        while (id != null) {
            Organization centity = getOrganizationEntity(id);
            if ((centity == null) || (centity.getParentid() == null)
                    || (centity.getParentid().trim().length() <= 0))
                id = null;
            else {
                id = centity.getParentid();
            }
            if (centity != null) {
                orgs.add(centity);
            }
        }
        Collections.reverse(orgs);
        return orgs;
    }

    public List<String> getOrgUsers(String orgid) {
        DataQuery query = DataQuery.getInstance(1, "a.id as id ,a.name as name",
                "ALONE_AUTH_USER a " +
                        "left join ALONE_AUTH_USERORG b on b.USERID=a.id " +
                        "left join ALONE_AUTH_ORGANIZATION c on c.ID=b.ORGANIZATIONID");
        query.setPagesize(1000);
        Organization org = getOrganizationEntity(orgid);
        query.addSqlRule(" and c.TREECODE like '" + org.getTreecode() + "%'");
        List<String> list = new ArrayList();
        try {
            for (Map node : query.search().getResultList())
                list.add((String) node.get("ID"));
        } catch (SQLException e) {
            e.printStackTrace();
            return list;
        }
        return list;
    }
}